package hu.pixelesztergalyos.continuity;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;

public class Character extends MosaicElement implements Tickable, Collideable,
		Drawable {
	public Level owner;                       // owner of the character for communication purposes
  private boolean isJumping = false;        // isJumping: character is currently in the elevating phase of the jump
  private boolean isFloating = false;       // isFloating: character is currently in the falling phase of the jump
  private float jumpStamina = JUMP_HEIGHT;  // jumpStamina: jump height
  private boolean hasKey;                   // hasKey: character has obtained the key
	private CharacterControls binds;
  private String color;                     // color: character color
  public int number;                        // number: identification number of the character

  private static final float JUMP_HEIGHT = 50.f;     // JUMP_HEIGHT: max height of a character's jump
  private static final float GRAVITY = 2.f;          // GRAVITY: Amount of drop / dt
  private static final float HORIZONTAL_SPEED = 1.f; // HORIZONTAL_SPEED: Amount of movement / dt
  private static final float JUMP_SPEED = 2.f;       // JUMP_SPEED: Amount of jump / dt
  private static final float CHARACTER_SIZE = 5.f;   // CHARACTER_SIZE: character's size within the mosaic

	// Constructor
	public Character(CharacterControls controls, Level owner, int number) {
		super();
     this.owner = owner;     // owner: setting for integrity reasons
     binds = controls;       // binds: the controls for the character
     this.number = number;   // number: identification number of the character
	}

	// HAXXED ÜBERLEET CPYCTR
	public Character(Character toCopy) {
		this.setBoundingBox(toCopy.getBoundingBox().width,
				toCopy.getBoundingBox().height);
		Point2D.Float temp_o = (Point2D.Float) toCopy.getOrigin().clone();
		this.number = toCopy.number;
		this.setOrigin(temp_o);
	}

	public Character(CharacterControls controls, float x, float y, Level owner,
			int number) {
		super(x, y);
		this.owner = owner;
		binds = controls;
		this.number = number;
		this.getBoundingBox().width = CHARACTER_SIZE;
		this.getBoundingBox().height = CHARACTER_SIZE;
	}

	/**
	 * 
	 * @return
	 * @throws IOException
	 */
	// The Character tries to move in the direction given in the parameter
	public void move(Direction direction) throws IOException {
		Character temp_c = new Character(this);
		Point2D.Float temp_o = temp_c.getOrigin();
		if (!isJumping) {
			// Gravity test
			temp_o.y += GRAVITY;
			temp_c.setOrigin(temp_o);
			if (owner.getCurrentMosaic().collisionDetectionBlock(temp_c, this)) {
				// Gravity did not cause a collision
				this.setOrigin(temp_o);
				isFloating = true;
			} else
				isFloating = false;
		} else { // Jump's stuff
			if (jumpStamina <= 0) {
				isJumping = false;
				isFloating = true;
				jumpStamina = JUMP_HEIGHT;
			} else {
				temp_c = new Character(this);
				temp_o.y -= JUMP_SPEED;
				temp_c.setOrigin(temp_o);
				if (!owner.getCurrentMosaic().collisionDetection(temp_c, this)) {
					// Collided with a wall
					isJumping = false;
					isFloating = true;
					jumpStamina = JUMP_HEIGHT;
				} else {
					this.setOrigin(temp_o);
					jumpStamina -= JUMP_SPEED;
				}
			}
		}

		// Movement test
		if (direction == null) {
			return; // e.g. no key was pressed
		}

		temp_c = new Character(this);
		temp_o = temp_c.getOrigin();

		if (direction == Direction.UP) {
			if (!isFloating) {
				isJumping = true;
			}
			temp_o.y -= JUMP_SPEED;
			temp_c.setOrigin(temp_o);

			if (!owner.getCurrentMosaic().collisionDetection(temp_c, this)) {
				isJumping = false;
			}
		} else {
			if (direction == Direction.RIGHT) {
				temp_o.x += HORIZONTAL_SPEED;   // if moving RIGHT, increase location.x by HORIZONTAL_SPEED
			}

			if (direction == Direction.LEFT) { 
				temp_o.x -= HORIZONTAL_SPEED;   // if moving LEFT, decrease location.x by HORIZONTAL_SPEED
			}

			temp_c.setOrigin(temp_o);

			if (owner.getCurrentMosaic().collisionDetection(temp_c, this)) {
				// If it's a valid move, move the character
				this.setOrigin(temp_o);
			}
		}
	}

	/**
	 * 
	 * @return
	 */

	// flag for signing if the character is jumping currently
	public void setIsJumping(boolean isJumping) {
		this.isJumping = isJumping;
	}

	/**
	 * 
	 * @return
	 */
	public boolean getIsJumping() {
		return isJumping;
	}

	/**
	 * 
	 * @return
	 */

	// if the character has collided with a key, we can store it with the help
	// of this setter
	public void setHasKey(boolean hasKey) {
		this.hasKey = hasKey;
	}

	/**
	 * 
	 * @return
	 */
	public boolean getHasKey() {
		return hasKey;
	}

	/**
	 * 
	 * @return
	 * @throws IOException
	 */
	public void tick() {
		if ((number != 2) || (owner.getCurrentMosaic().getHasCharacter2()))
		if (owner.owner.ks[binds.jump] && !isJumping) { //JAJJ DE PERGÉSMENTES
			try {
				move(Direction.UP); 
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else if (owner.owner.ks[binds.right]) {
			try {
				move(Direction.RIGHT);
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else if (owner.owner.ks[binds.left]) {
			try {
				move(Direction.LEFT);
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else {
			try {
				move(null);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	/**
	 * 
	 * @return
	 */
	public void draw() {
	}

	/**
	 * 
	 * @param Character
	 * @return
	 */
	public void hitBy(Character character) {
		// nothing happens
	}

	/**
	 * 
	 * @param BuildingBlock
	 * @return
	 * @throws IOException
	 */

	// the character collided with a building block
	public void hitBy(BuildingBlock buildingBlock) throws IOException {
	}

	/**
	 * 
	 * @param Gate
	 * @return
	 * @throws IOException
	 */
	// the character collided with a gate
	public void hitBy(Gate gate) throws IOException {
		if (this.hasKey) {
			owner.setIsCompleted(true);
		}

	}

	/**
	 * 
	 * @param Key
	 * @return
	 * @throws IOException
	 */

	// the character collided with a key
	public void hitBy(Key key) throws IOException {
		if (!hasKey) { // if the character hasn't got the key already,
			hasKey = true; // character gets the key
		}

	}

	/**
	 * 
	 * @param TransitionBlock
	 * @return
	 * @throws IOException
	 */
	// the character collided with a transitionblock
	public void hitBy(TransitionBlock transitionBlock) throws IOException {
		owner.testTransition(transitionBlock, this);
	}

  // Returns the type of the character
	public char getType() {
		if (color == "red")
			return 'p'; // red character
		else
			return 'q'; // black character
	}

}
